//demo实际没有什么具体电路或功能，大家注释语法即可，能看懂每句verilog是啥意思就可，不需要纠结整体，testbench_demo.v同理
module demo (
    input           clk,
    //时钟信号产生
    input           rst_n,
    //复位设置
    input   [3:0]   i_data,
    input   [3:0]   q_data,
    //实现4位数据传输
    input           ready_in,
    //控制数据进入并运算输出的开关
    input   [1:0]   sel,
    //决定运算方式
    output  [4:0]   out_data,
    //最终运算结果信号输出
    output          ready_out
    //输出开关状态
);
//定义两个寄存器存储输入数据和输出数据
    reg [3:0] i_data_reg;
    reg [3:0] q_data_reg;
    //定义两个四位存储输入待运算信号的寄存器
    reg [3:0] out_data_reg;
    //定义存储输出信号的寄存器

    reg [3:0] cnt;
    //定义4位 计数器数据存储器

    //计数器，存储运算次数
    always @(posedge clk or negedge rst_n)//在时钟上升沿和复位键下降沿开始
     begin
        if(!rst_n)
            cnt<=4'b0;
        //复位后，寄存器内数据清空
        else if(cnt==4'd8)
        //计数器计数位满后，寄存器内数据清空
            cnt<=4'b0;
        
        else 
        //正常情况下，每一次时钟周期计数器＋1
            cnt<=cnt+1'b1;
    end

    //reg in
    //在时钟上升沿和复位键下降沿开始
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            i_data_reg<=4'd0;
            //复位后，数据寄存器内数据清空
        else if(cnt==4'd4)
            i_data_reg<=4'd3;
        else if(ready_in)
            i_data_reg<=i_data;
    end
    //在时钟上升沿和复位键下降沿开始
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            q_data_reg<=4'd0;
            //复位后，数据寄存器内数据清空
        else if(cnt==4'd4)
            q_data_reg<=4'd3;
            //计数器为4时，q_data_reg赋值为3
        else if(ready_in)
            q_data_reg<=q_data;//ready_in有效时，
    end  

//-------------------------------------写法1------------------------------------------//
/*
    //MUX，中心运算器＋多路选择器，负责选择和运算逻辑的工作并将结果传给输出信号，本写法采用输出数据寄存器实现运算结果的储存
    always @(*) begin
        case (sel)
            2'b00:  out_data_reg = i_data_reg;
            2'b01:  out_data_reg = i_data_reg * q_data_reg;
            2'b10:  out_data_reg = i_data_reg & q_data_reg;
            2'b11:  out_data_reg = i_data_reg && q_data_reg;
            default:;
        endcase
    end

    assign out_data = out_data_reg;//输出数据寄存器实现信号的传输
    assign ready_out = ready_in;//输出开关状态
*/
/*
  * 这是一个组合逻辑块，用于根据sel信号的值选择并执行不同的运算
  * 当sel为00时，out_data_reg赋值为i_data_reg的值
  * 当sel为01时，out_data_reg赋值为i_data_reg和q_data_reg的乘积
  * 当sel为10时，out_data_reg赋值为i_data_reg和q_data_reg的按位与运算结果
  * 当sel为11时，out_data_reg赋值为i_data_reg和q_data_reg的逻辑与运算结果
  * 默认情况下，不执行任何操作
  */

//-------------------------------------写法2------------------------------------------//

    //MUX,中心运算器＋多路选择器，负责选择和运算逻辑的工作并将结果传给输出信号，与上一个的效果近似，本写法未采用输出数据寄存器
    assign out_data = (sel==2'b00) ?  i_data_reg : 
                      (sel==2'b01) ? (i_data_reg * q_data_reg) :
                      (sel==2'b10) ? (i_data_reg & q_data_reg) :
                                     (i_data_reg && q_data_reg);
    //输出开关状态
    assign ready_out = ready_in;

endmodule